package cn.lichenfei.jfx.music.gui;

import cn.hutool.core.lang.Console;
import cn.lichenfei.jfx.music.Application;
import cn.lichenfei.jfx.music.common.*;
import cn.lichenfei.jfx.music.common.enums.PlayType;
import cn.lichenfei.jfx.music.common.model.MusicInfo;
import cn.lichenfei.jfx.music.common.model.TimeInfo;
import cn.lichenfei.jfx.music.common.utils.JFUtils;
import javafx.animation.Interpolator;
import javafx.animation.RotateTransition;
import javafx.animation.Timeline;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.scene.SnapshotParameters;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.control.Tooltip;
import javafx.scene.effect.DropShadow;
import javafx.scene.effect.GaussianBlur;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.WritableImage;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.util.Duration;
import org.kordamp.ikonli.antdesignicons.AntDesignIconsOutlined;
import org.kordamp.ikonli.boxicons.BoxiconsRegular;
import org.kordamp.ikonli.javafx.FontIcon;

/**
 * @author ChenFei
 * @date 2022/4/21
 */
public class MusicHome extends StackPane implements PlayerResult {

    private final MusicPlayer musicPlayer = new MusicPlayer(this);//自定义音乐播放器
    //
    private RotateTransition rotate;//旋转动画
    private Pane backgroundPane = new Pane();
    private ImageView rotateImg = new ImageView();
    private static boolean is = false;

    {
        this.getStylesheets().addAll(Application.class.getResource("css/music-home.css").toExternalForm());
        this.getChildren().addAll(backgroundPane, rotateImg);
        //动画属性
        rotate = new RotateTransition(Duration.seconds(5), rotateImg);
        rotate.setFromAngle(0);
        rotate.setToAngle(360);
        rotate.setCycleCount(Timeline.INDEFINITE);//次数：无数次
        rotate.setInterpolator(Interpolator.LINEAR);//：每次旋转完的过渡:均匀过渡
    }

    //顶部区域
    private VBox topBox = new VBox();
    private Label titleLabel = new Label();
    private Label artistLabel = new Label();

    {
        this.getChildren().add(topBox);
        topBox.getChildren().addAll(titleLabel, artistLabel);
        this.setAlignment(topBox, Pos.TOP_CENTER);
        topBox.getStyleClass().add("top-box");
        titleLabel.getStyleClass().add("title-label");
        artistLabel.getStyleClass().add("artist-label");
    }

    //底部区域
    private VBox bottomBox = new VBox();
    //进度条部分
    private HBox progressBox = new HBox();
    private Label currentTimeLabel = new Label("00:00");
    private Slider progressLine = new Slider(0, 0, 0);
    private Label totalTimeLabel = new Label("99:99");
    ////底部操作区域
    private HBox butBox = new HBox();
    private Button playTypeBut = new Button();//播放类型
    private Button previousBut = new Button();//上一首
    private Button pauseStartBut = new Button();//暂停、开始
    private Button nextBut = new Button();//下一首
    private Button listBut = new Button();//播放列表

    {
        this.getChildren().add(bottomBox);
        this.setAlignment(bottomBox, Pos.BOTTOM_CENTER);
        bottomBox.getChildren().addAll(progressBox, butBox);
        progressBox.getChildren().addAll(currentTimeLabel, progressLine, totalTimeLabel);
        butBox.getChildren().addAll(playTypeBut, previousBut, pauseStartBut, nextBut, listBut);
        //图标
        playTypeBut.setGraphic(new FontIcon(AntDesignIconsOutlined.RETWEET));
        playTypeBut.setTooltip(new Tooltip("列表循环"));
        playTypeBut.getTooltip().setShowDelay(Duration.millis(100));
        previousBut.setGraphic(new FontIcon(AntDesignIconsOutlined.STEP_BACKWARD));
        pauseStartBut.setGraphic(new FontIcon(AntDesignIconsOutlined.CARET_RIGHT));//PAUSE
        nextBut.setGraphic(new FontIcon(AntDesignIconsOutlined.STEP_FORWARD));
        listBut.setGraphic(new FontIcon(AntDesignIconsOutlined.UNORDERED_LIST));
        //设置class
        progressBox.getStyleClass().add("progress-box");
        progressLine.getStyleClass().add("progress-line");
        bottomBox.getStyleClass().add("bottom-box");
        butBox.getStyleClass().add("but-box");
        playTypeBut.getStyleClass().add("bottom-but");
        previousBut.getStyleClass().add("bottom-but");
        pauseStartBut.getStyleClass().add("pause-start-but");
        nextBut.getStyleClass().add("bottom-but");
        listBut.getStyleClass().add("bottom-but");
        //播放，暂停音乐
        pauseStartBut.setOnMouseClicked(event -> {
            if (!is) {
                musicPlayer.play();
            } else {
                musicPlayer.pause();
            }
        });
        //监听进度条变化（主要监听手动改变进度条时）
        progressLine.valueProperty().addListener((observable, oldValue, newValue) -> {
            int abs = Math.abs(newValue.intValue() - oldValue.intValue());
            //如果监听到进度条播放异常（上传和这次的值间隔大于1秒）那不正常，就认为是拖动（那么就设置播放时间）
            if (abs > 1) {
                musicPlayer.setSeek(newValue.doubleValue());
                //
                TimeInfo timeInfo = new TimeInfo(newValue.intValue());
                progressLine.setValue(timeInfo.getTotalSeconds());//设置进度条
                currentTimeLabel.setText(timeInfo.getTimeStr());//设置当前时长数据
            }
        });
        //上一首，下一首
        previousBut.setOnMouseClicked(event -> musicPlayer.previousMusic());
        nextBut.setOnMouseClicked(event -> musicPlayer.nextMusic());
        //播放类型设置
        playTypeBut.setOnMouseClicked(event -> {
            setPlayType();
        });
        //显示Music列表页面
        listBut.setOnMouseClicked(event -> {
            MusicPane musicPane = JFUtils.getParent(this, MusicPane.class);
            musicPane.getMusicList().show();
        });
    }

    private void setPlayType() {
        PlayType playType = musicPlayer.getPlayType();
        switch (playType) {
            case LIST_CYCLE:
                playTypeBut.setGraphic(new FontIcon(BoxiconsRegular.SHUFFLE));
                playTypeBut.setText(null);
                playTypeBut.getTooltip().setText("随机播放");
                musicPlayer.setPlayType(PlayType.SHUFFLE);
                break;
            case SHUFFLE:
                playTypeBut.setGraphic(null);
                playTypeBut.setText("①");
                playTypeBut.getTooltip().setText("单曲循环");
                musicPlayer.setPlayType(PlayType.ONE_CYCLE);
                break;
            case ONE_CYCLE:
                playTypeBut.setGraphic(new FontIcon(AntDesignIconsOutlined.RETWEET));
                playTypeBut.setText(null);
                playTypeBut.getTooltip().setText("列表循环");
                musicPlayer.setPlayType(PlayType.LIST_CYCLE);
            default:
                break;
        }
    }

    private VBox rightBox = new VBox();
    private Label volumeLabel = new Label();
    private Slider volumeSlider = new Slider(0, 100, 50);
    private Button volumeBut = new Button();

    {
        this.getChildren().add(rightBox);
        this.setAlignment(rightBox, Pos.CENTER_RIGHT);
        rightBox.getChildren().addAll(volumeLabel, volumeSlider, volumeBut);
        volumeBut.setGraphic(new FontIcon(BoxiconsRegular.VOLUME_FULL));
        volumeSlider.setOrientation(Orientation.VERTICAL);
        //设置class，
        rightBox.getStyleClass().add("right-box");
        volumeSlider.getStyleClass().add("volume-slider");
        volumeBut.getStyleClass().add("volume-but");
        //设置音量步长
        volumeSlider.setBlockIncrement(5);
        //监听音量变化
        volumeSlider.valueProperty().addListener((observableValue, number, t1) -> {
            int i = t1.intValue();
            volumeLabel.setText(i + "");
            musicPlayer.setVolume(i);//设置音量大小
            if (i == 0) {
                volumeBut.setGraphic(new FontIcon(BoxiconsRegular.VOLUME_MUTE));
            } else {
                volumeBut.setGraphic(new FontIcon(BoxiconsRegular.VOLUME_FULL));
            }
        });
    }

    public MusicHome() {
        //setKeyEvent();//绑定键盘事件
        //播放类型
        setPlayType();
    }

    /**
     * 设置旋转图片信息
     */
    public void setRotateImgInfo(Image inImage) {
        rotateImg.setImage(inImage);
        rotateImg.setFitWidth(200);
        rotateImg.setFitHeight(200);
        //将图片设置为圆角
        Rectangle clip = new Rectangle(
                rotateImg.getFitWidth(), rotateImg.getFitHeight()
        );
        //圆角大小
        clip.setArcWidth(200);
        clip.setArcHeight(200);
        rotateImg.setClip(clip);
        //快照圆角图像
        SnapshotParameters parameters = new SnapshotParameters();
        parameters.setFill(Color.TRANSPARENT);//透明背景
        WritableImage image = rotateImg.snapshot(parameters, null);
        // 删除裁剪圆角设置
        rotateImg.setClip(null);
        // 设置阴影
        rotateImg.setEffect(new DropShadow(20, Color.valueOf("#606266")));
        // 设置圆角图像
        rotateImg.setImage(image);
    }

    /**
     * 播放音乐
     *
     * @param index
     */
    public void playMusic(int index) {
        musicPlayer.play(index);
    }

    public void pause() {
        musicPlayer.pause();
    }

    public void play() {
        musicPlayer.play();
    }

    @Override
    public void resultTimeInfo(TimeInfo maxTime) {
        totalTimeLabel.setText(musicPlayer.getTotalTime().getTimeStr());//设置音频总时长数据
        progressLine.setMax(musicPlayer.getTotalTime().getTotalSeconds());//设置进度条最大值
    }

    private GaussianBlur gaussianBlur = new GaussianBlur();

    @Override
    public void resultMediaInfo(MusicInfo musicInfo) {
        setRotateImgInfo(musicInfo.getImage());//设置旋转图片
        //设置音量相关
        volumeSlider.setValue(musicInfo.getVolume());
        volumeLabel.setText(musicInfo.getVolume().toString());
        //设置背景图片
        BackgroundImage backgroundImage = new BackgroundImage(musicInfo.getImage(), null, null, BackgroundPosition.CENTER, null);
        backgroundPane.setBackground(new Background(backgroundImage));
        //设置模糊度
        gaussianBlur.setRadius(50);
        backgroundPane.setEffect(gaussianBlur);
        //将背景设置为圆角
        Rectangle clip = new Rectangle(this.getWidth(), this.getHeight());
        //圆角大小
        clip.setArcWidth(8);
        clip.setArcHeight(8);
        backgroundPane.setClip(clip);
        //歌曲名称，歌词者
        titleLabel.setText(musicInfo.getTitle());
        artistLabel.setText(musicInfo.getArtist());
    }

    //音频数据监听
    @Override
    public void resultListener(double timestamp, double duration, float[] magnitudes, float[] phases, TimeInfo currentTime) {
        progressLine.setValue(currentTime.getTotalSeconds());//设置进度条
        currentTimeLabel.setText(currentTime.getTimeStr());//设置当前时长数据
    }

    @Override
    public void resultOnEnd() {
        progressLine.setValue(0);//设置进度条
        currentTimeLabel.setText("00:00");//设置当前时长数据
    }

    @Override
    public void resultPlay() {
        rotate.play();//图片旋转
        pauseStartBut.setGraphic(new FontIcon(AntDesignIconsOutlined.PAUSE));//改变按钮图片
        is = true;
    }

    @Override
    public void resultPause() {
        rotate.pause();//图片暂停旋转
        pauseStartBut.setGraphic(new FontIcon(AntDesignIconsOutlined.CARET_RIGHT));//改变按钮图片
        is = false;
    }

    /**
     * 设置键盘按下事件:
     */
    public void setKeyEvent() {
        this.setOnKeyPressed(event -> {
            KeyCode code = event.getCode();
            Console.log("keyCode:{}", code);
            switch (code) {
                case SPACE:
                    if (!is) {
                        musicPlayer.play();
                    } else {
                        musicPlayer.pause();
                    }
                    break;
                case LEFT:
                    musicPlayer.previousMusic();
                    break;
                case RIGHT:
                    musicPlayer.nextMusic();
                    break;
                case UP:
                    volumeSlider.setValue(volumeSlider.getValue() + 1);
                    break;
                case DOWN:
                    volumeSlider.setValue(volumeSlider.getValue() - 1);
                    break;
                default:
                    break;
            }
        });
        this.requestFocus();
        this.setOnMouseClicked(event -> this.requestFocus());
    }
}
